package com.csun.cmny.mqtt.core;

import com.csun.cmny.mqtt.constant.MqttMsgConstants;
import com.csun.cmny.mqtt.entity.MsgInviteClose;
import com.csun.cmny.mqtt.utils.JsonUtil;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-01-15 13:12
 * @Description: the abstract class mqtt client base
 */
public abstract class MqttClientBase {

    /**
     * mqtt 客户端
     */
    protected MqttClient mqttClient;

    /**
     * mqtt 服务器url
     */
    protected String url;

    /**
     * mqtt 客户端Id
     */
    protected String clientId;

    /**
     * mqtt 订阅主题
     */
    protected String topic;

    /**
     * mqtt 连接属性
     */
    protected MqttConnectOptions options;


    /**
     * mqtt client init
     *
     * @param subOptions    the mqtt client connect options
     *
     * @return  the boolean
     */
    public boolean mqttClientInit(MqttClientConnectOptions subOptions) {

        options = new MqttConnectOptions();

        /* 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接 */
        options.setCleanSession(subOptions.isCleanSession());

        /* 设置超时时间 单位为秒 */
        options.setConnectionTimeout(subOptions.getConnectionTimeout());

        /* 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制  */
        options.setKeepAliveInterval(subOptions.getKeepAliveInterval());

        /* 设置连接的密码   */
        options.setPassword(subOptions.getPassWord().toCharArray());

        /* 设置连接的用户名   */
        options.setUserName(subOptions.getUserName());

        topic = subOptions.getTopic();
        url = subOptions.getServerURI();
        clientId = subOptions.getClientId();

        return true;
    }

    /**
     * @Description: mqtt连接
     * @return boolean
     * @throws MqttException
     */
    public abstract boolean mqttClientStart(int[] qos, String[] topic,
                                            DeviceDataBase deviecData) throws MqttException;

    /**
     * @Description: mqtt连接
     * @return boolean
     */
    public boolean mqttClientStart() {

        try {

            /* 创建mqtt订阅客户端 */
            mqttClient = new MqttClient(url, clientId, new MemoryPersistence());

            /* 设置mqtt client掉线通知 */
            if (topic != null) {
                MqttTopic t = mqttClient.getTopic(topic);
                MsgInviteClose msgInviteClose = new MsgInviteClose(MqttMsgConstants.INVITE_CLOSE, clientId);
                options.setWill(t, JsonUtil.getInfoMap(msgInviteClose).getBytes(), 1, true);
            }

            /* mqtt订阅端连接服务器 */
            mqttClient.connect(options);

        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /**
     * @Description: mqtt重新连接
     * @return boolean
     */
    public abstract boolean mqttClientReConn();

    public boolean mqttClientClose() throws MqttException {
        mqttClient.disconnect();
        return true;
    }

}
